#pragma once

// Default Values 
#define DEFAULT_REPORT_INTERVAL                 0
#define MINIMUM_REPORT_INTERVAL                 0  
#define DEFAULT_ACCELERATION_G                  1.0F
#define DEFAULT_CHANGE_SENSITIVITY              0
#define MIN_CHANGE_SENSITIVITY                  0.0F
#define MAX_CHANGE_SENSITIVITY                  100.0F
#define RUMBLE_BIT								0		// WP7Accelerometer rumble is off by default
#define READ_CHANNELS_COUNT						1		// number of read channels to run

//
// Accelerometer sensor implementation.
//
class CAccelerometerSensor : public CSensor,
							 public CAsyncCallback
{
public:
	//
	// The report format in which the WP7Accelerometer should return data
	//
	enum InputReport
	{
		//
		// Status report
		//
		irStatus				= 0x20,
		//
		// Read data from memory location
		//
		irReadData			= 0x21,
		//
		// Register write complete
		//
		irOutputReportAck		= 0x22,
		//
		// Button data only
		//
		irButtons				= 0x30,
		//
		// Button and accelerometer data
		//
		irButtonsAccel		= 0x31,
		//
		// IR sensor and accelerometer data
		//
		irIRAccel				= 0x33,
		//
		// Button and extension controller data
		//
		irButtonsExtension	= 0x34,
		//
		// Extension and accelerometer data
		//
		irExtensionAccel		= 0x35,
		//
		// IR sensor, extension controller and accelerometer data
		//
		irIRExtensionAccel	= 0x37
	};

	//
	// WP7Accelerometer output commands
	//
	enum OutputReport
	{
		orLEDs				= 0x11,
		orType				= 0x12,
		orIR				= 0x13,
		orStatus			= 0x15,
		orWriteMemory		= 0x16,
		orReadMemory		= 0x17,
		orIR2				= 0x1a
	};

public:
	CAccelerometerSensor(void);
	virtual ~CAccelerometerSensor(void);

	//
	// Initialize this sensor.
	//
	virtual HRESULT Init(IWDFDevice *pDevice, CSensorDDI *pSensorDDI);

	//
	// Getters for accelerometer sensor properties.
	//
	virtual wstring GetId() const;						// retrieve sensor id
	virtual wstring GetName() const;					// retrieve name of the sensor
	virtual GUID GetFunctionalObjectCategory() const;	// retrieve functional object category

	//
	// start I/O cycle
	//
	virtual HRESULT StartIO(IWDFDevice* pDevice);

	//
	// stop I/O cycle
	//
	virtual HRESULT StopIO(IWDFDevice*);

protected:
	CComObject<CReadWriteRequest>	*m_pHidReadRequest[READ_CHANNELS_COUNT];	// I/O request manager read object
	CComObject<CReadWriteRequest>	*m_pHidWriteRequest;						// I/O request manager write object
	
	BYTE							m_x0, m_y0, m_z0;							// Zero point of accelerometer
	BYTE							m_xg, m_yg, m_zg;							// Gravity at rest of accelerometer
	INT32							m_rx, m_ry, m_rz;							// raw acceleration values recd from WP7Accelerometer
	FLOAT							m_fx, m_fy, m_fz;							// normalized acceleration values

	bool							m_bUseAltWriteMethod;						// Use HID IOCTL instead of stream write
	CRequestContext					m_RequestContext;							// context data used with requests that are
																				// in process

	//
	// I/O callback invoked by "CReadWriteRequest"
	//
	virtual void OnAsyncReadCallback(BYTE* buffer, ULONG length, void *context);

	virtual HRESULT WriteReport(BYTE *buffer, ULONG length);
	virtual HRESULT ReadMemory(ULONG address, ULONG length, PBYTE buffer);
	void ParseReadData(PBYTE buffer, ULONG length);
	void ParseAccelerationData(PBYTE buffer, ULONG length);
	void ReadCalibration();
};
